package com.fs.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fs.auth.TokenGenerator;
import com.fs.mapper.*;
import com.fs.pojo.*;
import com.fs.vo.PageResult;
import com.fs.vo.SysResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.awt.image.BufferedImage;
import java.util.*;
import com.google.code.kaptcha.Producer;

@RefreshScope
@Slf4j
@Service
public class SysAdminServiceImpl implements SysAdminService {

    @Value("${zyz.admin.enable-caption:true}")
    private Boolean enableAdminCaption;

    @Value("${zyz.admin.login-times:3}")
    private Integer adminLoginTimes;

    @Value("${zyz.admin.id:1}")
    private Integer superAdminId;

    @Autowired
    private SysCaptMapper captMapper;

    @Autowired
    private SysAdminMapper adminMapper;

    @Autowired
    private SysAdminTokenMapper adminTokenMapper;

    @Autowired
    private SysAdminMenusMapper sysAdminMenusMapper;

    @Autowired
    private SysAdminRolesMapper sysAdminRolesMapper;

    @Autowired
    private SysAdminAndRoleMapper sysAdminAndRoleMapper;

    @Override
    @Transactional
    public SysResult doLogin(SysAdmin admin) {
        if (admin == null) {
            return SysResult.fail();
        }
        String username = admin.getUsername();
        String password = admin.getPassword();
        String caption = admin.getCatpe();
        String captionUUID = admin.getUuid();

        //判断验证码图片
        if (enableAdminCaption) {
            if (caption == null || captionUUID == null) {
                return SysResult.fail("请输入验证码");
            }
            SysCapt captEntity = captMapper.selectById(captionUUID);
            if (captEntity == null) return SysResult.fail("验证码失效");
            Date expireTime = captEntity.getExpireTime();
            Date nowTime = new Date();
            if (expireTime.compareTo(nowTime) < 0) return SysResult.fail("验证码失效");
            if (!caption.equalsIgnoreCase(captEntity.getCode())) return SysResult.fail("验证码错误");
            //删除验证码
            captMapper.deleteById(captionUUID);
        }

        //判断用户名是否符合规则
        String usernameRegex = "^\\w{5,16}$";
        if (!username.matches(usernameRegex)) return SysResult.fail("用户名5-16位，字母或数字");

        //判断密码是否符合规则
        String passwordRegex = "^\\w{5,16}$";
        if (!password.matches(passwordRegex)) return SysResult.fail("密码5-16位，字母或数字");


        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        List<SysAdmin> adminEntityList = adminMapper.selectList(queryWrapper);
        if (adminEntityList.size() == 0) {
            return SysResult.fail("账户不存在");
        } else if (adminEntityList.size() > 1) {
            return SysResult.fail("账户重复");
        }
        SysAdmin adminEntity = adminEntityList.get(0);

        // 登陆次数是否超过限制
        Integer haveErrNum = adminEntity.getErrNum();
        if (haveErrNum >= adminLoginTimes) {
            return SysResult.fail("登陆次数达到" + adminLoginTimes + "次，账户已禁用");
        }

        //判断密码
        String md5 = SecureUtil.md5(password + adminEntity.getSalt());
        log.debug("登陆密码：{}",md5);
        if (!md5.equalsIgnoreCase(adminEntity.getPassword())) {
            //记录登陆失败次数、日期
            adminEntity.setErrNum(haveErrNum + 1);
            adminEntity.setErrTime(new Date());
            if (haveErrNum + 1 == adminLoginTimes) {
                adminEntity.setStatus(false);
                adminEntity.setErrTime(new Date());
                adminMapper.updateById(adminEntity);
                return SysResult.fail("登陆次数达到" + adminLoginTimes + "次，账户已禁用");
            }
            adminMapper.updateById(adminEntity);
            return SysResult.fail("登陆失败");
        }
        //判断状态
        if (!adminEntity.getStatus()) {
            return SysResult.fail("账户已禁用");
        }
        //登陆错误次数清零
        adminEntity.setErrNum(0);
        adminEntity.setErrTime(null);
        adminMapper.updateById(adminEntity);

        //生成token
        Map<String, Object> result = new HashMap<>();
        result.put("token", TokenGenerator.generateValue());
        result.put("username", adminEntity.getUsername());
        result.put("userId", adminEntity.getId());
        result.put("status", true);
        Calendar calendar = new GregorianCalendar();
        calendar.add(calendar.DATE, 1);
        result.put("expire_time", calendar.getTime());

        SysAdminToken tokenEntity = new SysAdminToken();
        tokenEntity.setUserId(adminEntity.getId());
        tokenEntity.setToken(result.get("token").toString());
        tokenEntity.setEndTime((Date) result.get("expire_time"));
        tokenEntity.setUpdated(new Date());
        if (adminTokenMapper.selectById(tokenEntity) == null) {
            adminTokenMapper.insert(tokenEntity);
        } else {
            adminTokenMapper.updateById(tokenEntity);
        }

        return SysResult.success(result);
    }

    @Override
    @Transactional
    public SysResult getCaption() {
        String uuid = UUID.randomUUID().toString();//.replace("-","");
        String code = RandomUtil.randomString(6);

        SysCapt captEntity = new SysCapt(uuid, code, new Date());
        int i = captMapper.insert(captEntity);
        return SysResult.success(captEntity);
    }

    @Override
    @Transactional
    public SysResult unLock(Integer id) {
        if(id.equals(superAdminId)){
            return SysResult.fail("超级管理员操作");
        }
        SysAdmin adminEntity = new SysAdmin();
        adminEntity.setId(id);
        adminEntity.setStatus(true);
        adminEntity.setErrNum(0);
        adminEntity.setErrTime(null);
        adminMapper.updateById(adminEntity);
        return SysResult.success();
    }

    @Transactional
    @Override
    public SysResult addAdmin(SysAdmin admin) {
        if (admin == null) return SysResult.fail();

        String username = admin.getUsername();
        String password = admin.getPassword();

        //判断用户名是否符合规则
        String usernameRegex = "^\\w{5,16}$";
        if (!username.matches(usernameRegex)) return SysResult.fail("用户名5-16位，字母或数字");

        //判断密码是否符合规则
        String passwordRegex = "^\\w{5,16}$";
        if (!password.matches(passwordRegex)) return SysResult.fail("密码5-16位，字母或数字");

        //判断用户名是否重复
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username);
        SysAdmin one = adminMapper.selectOne(queryWrapper);
        if(one!=null){
            return SysResult.fail("用户名重复");
        }

        //检测角色是否正确
        SysAdminRoles rolesEntity = sysAdminRolesMapper.selectById(admin.getRole());
        if(rolesEntity==null){
            return SysResult.fail("角色选择不正确");
        }

        Date date = new Date();
        String salt = RandomUtil.randomString(8);
        admin.setPassword(SecureUtil.md5(password + salt))
                .setSalt(salt)
                .setStatus(true)
                .setCreated(date)
                .setUpdated(date);
        adminMapper.insert(admin);

        //添加角色-admin表
        SysAdminAndRoles adminAndRole=new SysAdminAndRoles();
        adminAndRole.setRoleId(admin.getRole())
                .setUserId(Long.valueOf(admin.getId()));
        sysAdminAndRoleMapper.insert(adminAndRole);

        return SysResult.success();
    }

    @Transactional
    @Override
    public SysResult pwdAdmin(SysAdmin admin) {
        if (admin == null) return SysResult.fail();

        String username=admin.getUsername();
        //判断用户名是否符合规则
        String usernameRegex = "^\\w{5,16}$";
        if (!username.matches(usernameRegex)) return SysResult.fail("用户名5-16位，字母或数字");

        Date date = new Date();
        SysAdmin adminUpdate = new SysAdmin();
        adminUpdate.setId(admin.getId())
                .setUsername(username)
                .setUpdated(date);

        String password = admin.getPassword();
        if(password!=null && password.length()>0){
            //判断密码是否符合规则
            String passwordRegex = "^\\w{5,16}$";
            if (!password.matches(passwordRegex)) return SysResult.fail("密码5-16位，字母或数字");
            String salt = RandomUtil.randomString(8);
            String md5 = SecureUtil.md5(password + salt);
            adminUpdate.setPassword(md5)
                    .setSalt(salt);
        }
        adminMapper.updateById(adminUpdate);

        SysAdminAndRoles adminAndRole=new SysAdminAndRoles();
        adminAndRole.setRoleId(admin.getRole())
                .setUserId(Long.valueOf(admin.getId()));

        QueryWrapper<SysAdminAndRoles> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",admin.getId());
        sysAdminAndRoleMapper.update(adminAndRole,queryWrapper);
        return SysResult.success();
    }

    @Transactional
    @Override
    public SysResult enableAdmin(Integer id, Boolean status) {
        if(id.equals(superAdminId)){
            return SysResult.fail("超级管理员禁止操作");
        }

        SysAdmin adminEntity = new SysAdmin().setId(id).setStatus(status);
        if(status){
            adminEntity.setErrNum(0)
                    .setErrTime(null);
        }
        adminMapper.updateById(adminEntity);
        return SysResult.success();
    }

    @Override
    public SysResult adminList(PageResult requestVO) {
        int pageNum=requestVO.getPageNum();
        int pageSize=requestVO.getPageSize();

        if(pageNum<0)pageNum=1;
        if(pageSize<0) pageSize=10;

        Page<SysAdmin> page = new Page<>(pageNum,pageSize);
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.hasLength(requestVO.getQuery()),"username", requestVO.getQuery())
                .orderByDesc("id");

        page = adminMapper.selectPage(page, queryWrapper);
        requestVO.setTotal(page.getTotal()).setRows(page.getRecords());
        return SysResult.success(requestVO);
    }

    @Override
    public SysResult adminMenu(Long userId) {
//        List<String> adminMenu = adminDao.getAdminMenu(userId);
        QueryWrapper<SysAdminMenus> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",0);
        List<SysAdminMenus> list = sysAdminMenusMapper.selectList(queryWrapper);
        for (SysAdminMenus r : list) {
            queryWrapper.clear();
            queryWrapper.eq("parent_id",r.getId());
            r.setChildren(sysAdminMenusMapper.selectList(queryWrapper));
        }
        return SysResult.success(list);
    }
    @Autowired
    private Producer producer;

    @Override
    @Transactional
    public BufferedImage getCaptcha(String uuid) {
        if(StrUtil.isBlank(uuid)){
            return null;
//            throw new Exception("uuid不能为空");
        }
        String code = producer.createText();

        //5分钟后过期
        Date date = new Date();
        SysCapt captEntity = new SysCapt(uuid, code, DateUtil.offsetMinute(date,5));

        try {
            captMapper.insert(captEntity);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        //删除5分钟过期的
        captMapper.delete(new QueryWrapper<SysCapt>().lt("expire_time",DateUtil.offsetMinute(date,-5)));

        return producer.createImage(code);
    }

    @Override
    public SysResult getById(Integer id) {
        SysAdmin adminEntity = adminMapper.selectByIdAndRole(id);
        adminEntity.setPassword(null);
        adminEntity.setSalt(null);
        return SysResult.success(adminEntity);

//        Map<String,Object> adminEntity= adminDao.selectByIdAndRole(id);
//        return ResultVO.success(adminEntity);
    }

    @Transactional
    @Override
    public SysResult delById(Integer id) {
        if(id.equals(superAdminId)){
            return SysResult.fail("超级管理员禁止删除");
        }
        adminMapper.deleteById(id);
        return SysResult.success();
    }
}
